package com.woniu.zsd.recycle.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.zsd.common.util.Result;
import com.woniu.zsd.platform.FeignClient.StationFeignClient;
import com.woniu.zsd.recycle.dto.*;
import com.woniu.zsd.recycle.mapper.*;
import com.woniu.zsd.recycle.model.*;
import com.woniu.zsd.recycle.param.*;
import com.woniu.zsd.recycle.service.MqttGateway;
import com.woniu.zsd.recycle.service.RecyclingOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.zsd.user.feign.UserFeignClient;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 彭于晏
 * @since 2025年02月18日
 */
@Service
public class RecyclingOrderServiceImpl extends ServiceImpl<RecyclingOrderMapper, RecyclingOrder> implements RecyclingOrderService {

    @Resource
    private RecyclingOrderMapper recyclingOrderMapper;
    @Resource
    private RecyclingOrderDetailMapper recyclingOrderDetailMapper;
    @Resource
    private MaterialTypeMapper materialTypeMapper;
    @Resource
    private WastePricingMapper wastePricingMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private StationFeignClient stationFeignClient;
    @Resource
    private MqttGateway mqttGateway;
    @Resource
    private RecyclingRecordMapper recyclingRecordMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private UserFeignClient userFeignClient;
    @Override
    public void addRecyclingOrder(AddRecyclingOrderParam param) throws Exception {
        RecyclingOrder bean = BeanUtil.toBean(param, RecyclingOrder.class);
        String num = UUID.randomUUID().toString().replace("-", "");
        bean.setRecyclingOrderNum(num);
        RLock lock = redissonClient.getFairLock(bean.getRecyclingOrderNum());
        try {
            lock.lock();
            LocalDateTime now = LocalDateTime.now();
            bean.setCreatedAt(now);
            bean.setAppointmentTime(param.getAppointmentTime());
            bean.setUpdatedAt(now);
            bean.setStatus(1);// 1表示待接单2表示已接单3表示已取消4表示待评价5表示已评价6表示骑手取件中
            Result result = stationFeignClient.selectRecycleBinByLocation(param.getLongitude(), param.getLatitude());
            System.out.println(result+"=========================================");
            System.out.println(result.toString());
            List<Integer> data = (List<Integer>) result.getData();
            if (data==null || data.size() == 0){
                throw new Exception("该地点附近20km内暂无站点");
            }
            bean.setStationId(data.get(0));
            mqttGateway.sendToMqtt("station","收到新订单id:"+bean.getRecyclingOrderNum());
            recyclingOrderMapper.insert(bean);
            RecyclingOrderDetail detail = new RecyclingOrderDetail();
            detail.setRecyclingOrderNum(num);
            detail.setType(param.getType());
            recyclingOrderDetailMapper.insert(detail);
            DataParam dataParam = new DataParam();
            dataParam.setRecyclingOrderNum(num);
            dataParam.setData(data);
            dataParam.setT(0);
            System.out.println("站点"+data.get(0)+"收到新订单");
            try {
                String jsonStr = JSONUtil.toJsonStr(dataParam);
                rabbitTemplate.convertAndSend("waiting_allocation_station_queue",jsonStr);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println("发送消息到待分配站点队列");
            rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
                if (ack) {
                    System.out.println("消息发送成功");
                } else {
                    System.err.println("消息发送失败: " + cause);
                }
            });
        }finally {
            lock.unlock();
        }

    }

    @Override
    public void receivingOrders(ReceivingOrdersParam param) throws Exception {
        RecyclingOrder recyclingOrder = recyclingOrderMapper.selectById(param.getRecyclingOrderNum());
        recyclingOrder.setStatus(2);// 2表示已接单
        recyclingOrder.setStationId(param.getStationId());
        Result result = stationFeignClient.selectStationNameByStationId(param.getStationId());
        String stationName = (String) result.getData();
        recyclingOrder.setStationName(stationName);
        recyclingOrder.setUpdatedAt(LocalDateTime.now());
        recyclingOrderMapper.updateById(recyclingOrder);
    }

    @Override
    public void confirmVisit(ConfirmVisitParam param) throws Exception {
        RecyclingOrder recyclingOrder = recyclingOrderMapper.selectById(param.getRecyclingOrderNum());
        if (recyclingOrder == null){
            throw new Exception("订单不存在");
        }
        recyclingOrder.setStatus(6);// 6表示骑手取件中
        recyclingOrder.setDeliverName(param.getDeliverName());
        recyclingOrder.setDeliverPhone(param.getDeliverPhone());
        recyclingOrder.setUpdatedAt(LocalDateTime.now());
        recyclingOrderMapper.updateById(recyclingOrder);
    }

    @Override
    public void cancelRecyclingOrder(String recyclingOrderNum) throws Exception {
        RecyclingOrder recyclingOrder = recyclingOrderMapper.selectById(recyclingOrderNum);
        if (recyclingOrder == null){
            throw new Exception("订单不存在");
        }
        recyclingOrder.setStatus(3);// 3表示已取消
        recyclingOrder.setUpdatedAt(LocalDateTime.now());
        recyclingOrderMapper.updateById(recyclingOrder);
    }

    @Override
    public void confirmOrder(ConfirmOrderParam param) throws Exception {
        RecyclingOrder recyclingOrder = recyclingOrderMapper.selectById(param.getRecyclingOrderNum());
        if (recyclingOrder == null){
            throw new Exception("订单不存在");
        }
        //得到类型名称
        Integer stationId = recyclingOrder.getStationId();
        String typeName = materialTypeMapper.selectById(param.getMaterialTypeId()).getTypeName();
        //得到废品单价
        QueryWrapper<WastePricing> wrapper = new QueryWrapper<>();
        wrapper.eq("site_id",stationId);
        wrapper.eq("material_type_id",param.getMaterialTypeId());
        WastePricing wastePricing = wastePricingMapper.selectOne(wrapper);
        if (wastePricing == null){
            throw new Exception("该站点未配置该类垃圾的单价");
        }
        //计算价格
        BigDecimal decimal = wastePricing.getPrice().multiply(param.getActualWeight()).setScale(2, RoundingMode.HALF_UP);
        //积分
        int point = decimal.intValue();
        //更新订单
        recyclingOrder.setStatus(4);// 4表示待评价
        recyclingOrder.setUpdatedAt(LocalDateTime.now());
        recyclingOrderMapper.updateById(recyclingOrder);
        //新增回收订单详情表
        RecyclingOrderDetail recyclingOrderDetail = new RecyclingOrderDetail();
        recyclingOrderDetail.setRecyclingOrderNum(param.getRecyclingOrderNum());
        recyclingOrderDetail.setPrice(decimal);
        recyclingOrderDetail.setPoint(point);
        recyclingOrderDetail.setType(typeName);
        recyclingOrderDetail.setActualWeight(param.getActualWeight());
        recyclingOrderDetail.setRemarks(param.getRemarks());
        recyclingOrderDetailMapper.insert(recyclingOrderDetail);
        Integer userId = recyclingOrder.getUserId();
        //用户服务更新积分
        userFeignClient.addUserPoint(userId,point);
        //发送消息到评价队列
        rabbitTemplate.convertAndSend("","waiting_appraise_queue",param.getRecyclingOrderNum());
    }

    @Override
    public List<SelectOrderByIdDto> selectOrderById(Integer stationId) throws Exception {
        QueryWrapper<RecyclingOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("station_id",stationId);
        wrapper.eq("status",1);
        List<RecyclingOrder> recyclingOrders = recyclingOrderMapper.selectList(wrapper);
        if (recyclingOrders==null||recyclingOrders.size()==0){
            throw new Exception("该站点暂无待接单订单");
        }
        return BeanUtil.copyToList(recyclingOrders, SelectOrderByIdDto.class);
    }

    @Override
    public List<RecycleDtatistics> select(LocalDateTime startOfDay,LocalDateTime endOfDay) throws Exception {
        List<RecycleDtatistics> recycleDtatistics = recyclingRecordMapper.selectRecycleStatistics(startOfDay, endOfDay);
        for (RecycleDtatistics recycleDtatistic : recycleDtatistics) {
            QueryWrapper<MaterialType> wrapper = new QueryWrapper<>();
            wrapper.eq("type_name",recycleDtatistic.getMaterialType());
            MaterialType materialType = materialTypeMapper.selectOne(wrapper);
            QueryWrapper<WastePricing> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("material_type_id",materialType.getMaterialTypeId());
            queryWrapper.eq("site_id",recycleDtatistic.getStationId());
            WastePricing wastePricing = wastePricingMapper.selectOne(queryWrapper);
            BigDecimal multiply = wastePricing.getPrice().multiply(recycleDtatistic.getAllAmount());
            recycleDtatistic.setMoney(multiply);
        }
        return recycleDtatistics;
    }

    @Override
    public List<RecyclingOrder> selectAllOrderByUserId(Integer userId) throws Exception {
        QueryWrapper<RecyclingOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        List<RecyclingOrder> orders = recyclingOrderMapper.selectList(wrapper);
        if (orders==null){
            throw new Exception("该用户暂无订单");
        }

        return orders;
    }

    @Override
    public List<SelectCancelOrderByUserIdDro> selectCancelOrderByUserIdAndStatus(Integer userId, Integer status) throws Exception {
        QueryWrapper<RecyclingOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        wrapper.eq("status",status);
        List<RecyclingOrder> orders = recyclingOrderMapper.selectList(wrapper);
        if (orders==null){
            throw new Exception("该用户暂无该类状态订单");
        }
        List<SelectCancelOrderByUserIdDro> Dtos = BeanUtil.copyToList(orders, SelectCancelOrderByUserIdDro.class);
        return Dtos;
    }

    @Override
    public PageInfo<SelectOrderByConditionDto> selectOrderByCondition(ConditionParam param) throws Exception {
        //开启分页
        PageHelper.startPage(param.getPageNum(),param.getPageSize());
        List<SelectOrderByConditionDto> dtos=recyclingOrderMapper.selectOrderByCondition(param);
        if (dtos==null){
            throw new Exception("暂无符合条件的订单");
        }
        // 使用 PageInfo 包装查询结果
        PageInfo<SelectOrderByConditionDto> pageInfo = new PageInfo<>(dtos);
        return pageInfo;
    }

    @Override
    public PageInfo<SelectOrderByConditionDto> stationSelectOrderByCondition(StationConditionParam param) throws Exception {
        //开启分页
        PageHelper.startPage(param.getPageNum(),param.getPageSize());
        List<SelectOrderByConditionDto> dtos=recyclingOrderMapper.stationSelectOrderByCondition(param);
        System.out.println("数据库查询结果："+dtos);
        PageInfo<SelectOrderByConditionDto> selectOrderByConditionDtoPageInfo = new PageInfo<>(dtos);
        System.out.println("分页查询结果："+selectOrderByConditionDtoPageInfo);
        return selectOrderByConditionDtoPageInfo;
    }

    @Override
    public List<OrderDtoByStation> selectAllOrderByStation() throws Exception {
        // 获取今天的日期
        LocalDate today = LocalDate.now();

        // 获取今天的开始时间：00:00:00
        LocalDateTime startOfDay = today.atStartOfDay();

        // 获取今天的结束时间：23:59:59
        LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
        List<OrderDtoByStation> orderDtoByStations = recyclingOrderMapper.selectAllOrderByStation(startOfDay, endOfDay);
        return orderDtoByStations;
    }

    @Override
    public List<selectAllOrderByType> selectAllOrderByType() throws Exception {
        // 获取今天的日期
        LocalDate today = LocalDate.now();

        // 获取今天的开始时间：00:00:00
        LocalDateTime startOfDay = today.atStartOfDay();

        // 获取今天的结束时间：23:59:59
        LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
        List<selectAllOrderByType> dtos = recyclingOrderMapper.selectAllOrderByType(startOfDay, endOfDay);

        return dtos;
    }
}
